package com.xiaoshuidi.cloud.module.contract.service.contract.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageParam;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.mybatis.core.util.MyBatisUtils;
import com.xiaoshuidi.cloud.module.contract.controller.app.invoice.vo.InvoiceRespVO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.bill.OrderFeesDO;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.bill.OrderFeesMapper;
import com.xiaoshuidi.cloud.module.contract.vo.CompanyInvoiceReqVO;
import com.xiaoshuidi.cloud.module.contract.vo.CompanyInvoiceRespVO;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.bill.RentOrderMapper;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractInvoiceService;
import com.xiaoshuidi.cloud.module.finance.api.invoice.InvoiceApi;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ContractInvoiceServiceImpl implements ContractInvoiceService {
    @Resource
    private RentOrderMapper rentOrderMapper;
    @Resource
    private OrderFeesMapper orderFeesMapper;
    @Resource
    private InvoiceApi invoiceApi;
    /**
     * 开票金额类型: 租金
     */
    private final Integer invoiceFeeTypeRent = 1;
    /**
     * 开票金额类型: 其它
     */
    private final Integer invoiceFeeTypeOther = 2;

    /**
     * 企业可开票列表
     * @param reqVO
     * @return
     */
    @Override
    public PageResult<CompanyInvoiceRespVO> getCompanyInvoiceablePage(CompanyInvoiceReqVO reqVO) {
        CommonResult<Set<Long>> feeIdList = invoiceApi.invoicableFeeId(reqVO.getInvoiceConfigId());
        if (Objects.equals(reqVO.getInvoiceFeeType(), invoiceFeeTypeRent)) {
            reqVO.setFeeIds(Collections.singletonList(1L));
        } else {
            reqVO.setFeeIds(feeIdList.getData().stream().filter(f -> f != 1L).collect(Collectors.toList()));
        }
        if (CollectionUtils.isEmpty(reqVO.getFeeIds())) {
            return new PageResult<>();
        }
        IPage<CompanyInvoiceRespVO> page = MyBatisUtils.buildPage(reqVO);
        rentOrderMapper.selectCompanyInvoiceable(reqVO, page);
        page.getRecords().forEach(i -> i.setInvoiceFeeType(reqVO.getInvoiceFeeType()));
        return new PageResult<>(page.getRecords(), page.getTotal());
    }

    /**
     * 企业可开票费项明细
     * @param reqVO
     * @return
     */
    @Override
    public List<CompanyInvoiceRespVO> getCompanyInvoiceable(CompanyInvoiceReqVO reqVO) {
        // 由finance服务调用, feeIdList由finance服务设置好了
        return rentOrderMapper.selectCompanyInvoiceableDetail(reqVO);
    }

    /**
     * 更新开票记录id(RPC调用)
     * @param invoiceRecordId 开票记录id
     * @param feeDetailId
     */
    @Override
    public void setInvoiceRecordId(Long invoiceRecordId, List<Long> feeDetailId) {
        if (invoiceRecordId == null || CollectionUtils.isEmpty(feeDetailId)) {
            return;
        }
        orderFeesMapper.update(null, new UpdateWrapper<OrderFeesDO>()
                .in("id", feeDetailId)
                .set("invoice_status", 1)
                .set("invoice_record_id", invoiceRecordId)
        );
    }

    /**
     * 租客可开票账单列表
     * @param memberId
     * @param reqVO
     * @return
     */
    @Override
    public PageResult<InvoiceRespVO> getCustomerInvoiceablePage(Long memberId, PageParam reqVO) {
        IPage<InvoiceRespVO> page = rentOrderMapper.selectInvoiceable(memberId, MyBatisUtils.buildPage(reqVO));
        /*if (CollectionUtils.isNotEmpty(page.getRecords())) {
            // 按门店把账单分组
            Map<Long, List<InvoiceRespVO>> apartmentOrderMap = page.getRecords().stream().collect(Collectors.groupingBy(InvoiceRespVO::getApartmentId));
            // 按门店返回配置了税率的费项id
            CommonResult<Map<Long, List<Long>>> feeTaxMap = invoiceApi.getInvoiceTaxMap(apartmentOrderMap.keySet());
            if (feeTaxMap.isSuccess()) {
                // 获取所有可开票费用明细
                List<OrderFeesDO> l = orderFeesMapper.selectBatchIds(page.getRecords().stream().flatMap(InvoiceRespVO::getFeeIdStream).collect(Collectors.toList()));
                // 按账单id分组
                Map<Long, List<OrderFeesDO>> orderFeeMap = l.stream().collect(Collectors.groupingBy(OrderFeesDO::getOrderId));
                // 过滤配置了税率的费用明细
                apartmentOrderMap.forEach((k, v) -> {
                    Map<Long, List<OrderFeesDO>> newOrderFeeMap = v.stream().flatMap(o -> orderFeeMap.get(o.getOrderId()).stream())
                            .filter(f -> feeTaxMap.getData().get(k).contains(f.getFeeId()))
                            .collect(Collectors.groupingBy(OrderFeesDO::getOrderId));
                    v.forEach(r -> {
                        // 租金需要单独开票
                        if (Objects.equals(r.getInvoiceFeeType(), invoiceFeeTypeRent)) {
                            BigDecimal rent = newOrderFeeMap.get(r.getOrderId()).stream().filter(f -> f.getFeeId() == 1)
                                    .map(OrderFeesDO::getAmount)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            // 未配置租金税率时
                            if (rent.compareTo(BigDecimal.ZERO) == 0) {
                                r.setInvoicableAmount(BigDecimal.ZERO);
                            }
                        // 其它费用
                        } else {
                            List<String> feeDetailId = new ArrayList<>();
                            BigDecimal other = newOrderFeeMap.get(r.getOrderId()).stream().filter(f -> f.getFeeId() != 1)
                                    .peek(f -> feeDetailId.add(f.getId().toString()))
                                    .map(OrderFeesDO::getAmount)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            r.setInvoicableAmount(other);
                            r.setFeeDetailId(String.join(",", feeDetailId));
                        }
                    });

                });

            }

        }*/
        return new PageResult<>(page.getRecords(), page.getTotal());
    }
}
